#include "main.h"
#include "nucCommu.h"
#include "bsp_nucCom.h"
#include "robot_total_mode.h"
#include "struct_typedef.h"
#include "detect_task.h"
#include "OLED.h"
#include "cmsis_os.h"
#include "string.h"
#include "bsp_usart.h"
#include "naive_gimbal_task.h"
#include "debugConfig.h"

#include "referee.h"    // new

extern UART_HandleTypeDef huart1;
extern DMA_HandleTypeDef hdma_usart1_rx;

#define NUC_DATA_AVAILABLE 1
#define NUC_DATA_NOT_AVAILABLE 0


uint32_t gimbalreadmark = NUC_DATA_NOT_AVAILABLE;  //锟斤拷锟斤拷使锟矫憋拷志锟斤拷值为锟斤拷锟斤拷锟斤拷锟斤拷莶锟斤拷锟斤拷茫锟斤拷锟绞癸拷霉锟斤拷锟斤拷锟街滴伙拷锟斤拷锟斤拷锟斤拷菘锟斤拷茫锟斤拷锟斤拷锟斤拷蘸锟斤拷锟轿达拷锟绞癸拷茫锟�
uint32_t shootreadmark = NUC_DATA_NOT_AVAILABLE;

static void sbus_to_nucCtrl(volatile const uint8_t *sbus_buf, toSTM32_t *nuc_info);
//nuc control data 
//nuc锟斤拷锟狡憋拷锟斤拷
toSTM32_t nuc_ctrl;

//receive data, 44 bytes one frame, but set 88 bytes 
//锟斤拷锟斤拷原始锟斤拷锟捷ｏ拷为44锟斤拷锟街节ｏ拷锟斤拷锟斤拷88锟斤拷锟街节筹拷锟饺ｏ拷锟斤拷止DMA锟斤拷锟斤拷越锟斤拷
static uint8_t nucinfo_rx_buf[2][NUCINFO_RX_BUF_NUM];
// 锟结供锟竭诧拷畏锟阶帮拷锟斤拷锟斤拷锟街憋拷锟斤拷锟斤拷媒系筒锟斤拷头锟侥硷拷
void nuc_control_init(void)
{
    NUC_com_init(nucinfo_rx_buf[0], nucinfo_rx_buf[1], NUCINFO_RX_BUF_NUM);
}

//校锟斤拷锟斤拷锟街�
uint32_t CheckSum(toSTM32_t* data)
{
    uint32_t verification = 0;
	uint32_t *p;
	p = (uint32_t*)(data);
	int i;
    for(i=1;i<9;i++)
    {
        verification += ~p[i];
    }
    return verification;
}

/**
  * @brief          锟斤拷取nuc锟斤拷锟斤拷指锟斤拷
  * @param[in]      none
  * @retval         nuc锟斤拷锟斤拷指锟斤拷
  */

// 锟结供实时锟斤拷锟铰碉拷NUC锟斤拷锟斤拷锟接︼拷锟斤拷锟斤拷锟街革拷锟�
const toSTM32_t *get_nuc_control_point(void)
{
    return (const toSTM32_t*)&nuc_ctrl;
}



//锟斤拷锟斤拷锟斤拷莸慕锟斤拷锟阶刺�
//锟斤拷台
void gimbal_set_read_mark(void)
{
    gimbalreadmark = NUC_DATA_AVAILABLE;   //锟斤拷锟捷刚刚憋拷锟斤拷锟秸ｏ拷锟斤拷未使锟斤拷
}

void gimbal_clear_read_mark(void)
{
    gimbalreadmark = NUC_DATA_NOT_AVAILABLE;
}

int gimbal_NUC_is_available(void)
{
    return (gimbalreadmark == NUC_DATA_AVAILABLE);
}
//锟斤拷锟斤拷
void shoot_set_read_mark(void)
{
    shootreadmark = NUC_DATA_AVAILABLE;   //锟斤拷锟捷刚刚憋拷锟斤拷锟秸ｏ拷锟斤拷未使锟斤拷
}

void shoot_clear_read_mark(void)
{
    shootreadmark = NUC_DATA_NOT_AVAILABLE;
}

int shoot_NUC_is_available(void)
{
    return (shootreadmark == NUC_DATA_AVAILABLE);
}

// 锟斤拷锟斤拷NUC锟斤拷锟斤拷锟角凤拷锟斤拷锟斤拷锟�
static int verifiy_pass(void)
{
    int8_t i;
    uint8_t sum = 0;
    uint8_t * data = (uint8_t *) &nuc_ctrl;
    for(i=1;i<sizeof(toSTM32_t)-2;i++)
        sum += data[i];
    if(nuc_ctrl.checksum == sum)
        return 1;
    else
        return 0;
}

//锟斤拷锟斤拷锟叫讹拷
void USART1_IRQHandler(void)
{
    if(huart1.Instance->SR & UART_FLAG_RXNE)//锟斤拷锟秸碉拷锟斤拷锟斤拷//锟斤拷锟斤拷锟叫讹拷
    {
        __HAL_UART_CLEAR_PEFLAG(&huart1);
    }
    else if(USART1->SR & UART_FLAG_IDLE)//锟斤拷锟斤拷锟叫讹拷
    {
        static uint16_t this_time_rx_len = 0;

        __HAL_UART_CLEAR_PEFLAG(&huart1);

        if ((hdma_usart1_rx.Instance->CR & DMA_SxCR_CT) == RESET)
        {
            /* Current memory buffer used is Memory 0 */
    
            //disable DMA
            //失效DMA
            __HAL_DMA_DISABLE(&hdma_usart1_rx);

            //get receive data length, length = set_data_length - remain_length
            //锟斤拷取锟斤拷锟斤拷锟斤拷锟捷筹拷锟斤拷,锟斤拷锟斤拷 = 锟借定锟斤拷锟斤拷 - 剩锟洁长锟斤拷
            this_time_rx_len = NUCINFO_RX_BUF_NUM- hdma_usart1_rx.Instance->NDTR;

            //reset set_data_lenght
            //锟斤拷锟斤拷锟借定锟斤拷锟捷筹拷锟斤拷
            hdma_usart1_rx.Instance->NDTR = NUCINFO_RX_BUF_NUM;

            //set memory buffer 1
            //锟借定锟斤拷锟斤拷??1
            hdma_usart1_rx.Instance->CR |= DMA_SxCR_CT;
            
            //enable DMA
            //使锟斤拷DMA
            __HAL_DMA_ENABLE(&hdma_usart1_rx);

            if(this_time_rx_len == NUCINFO_FRAME_LENGTH)
            {   
                sbus_to_nucCtrl(nucinfo_rx_buf[0], &nuc_ctrl);
                if(verifiy_pass())
                {
                    detect_hook(MINI_PC_TOE);
                    gimbal_set_read_mark();
                    shoot_set_read_mark();
                }
            }
        }
        else
        {
            /* Current memory buffer used is Memory 1 */
            //disable DMA
            //失效DMA
            __HAL_DMA_DISABLE(&hdma_usart1_rx);

            //get receive data length, length = set_data_length - remain_length
            //锟斤拷取锟斤拷锟斤拷锟斤拷锟捷筹拷锟斤拷,锟斤拷锟斤拷 = 锟借定锟斤拷锟斤拷 - 剩锟洁长锟斤拷
            this_time_rx_len = NUCINFO_RX_BUF_NUM - hdma_usart1_rx.Instance->NDTR;

            //reset set_data_lenght
            //锟斤拷锟斤拷锟借定锟斤拷锟捷筹拷锟斤拷
            hdma_usart1_rx.Instance->NDTR = NUCINFO_RX_BUF_NUM;

            //set memory buffer 0
            //锟借定锟斤拷锟斤拷??0
            DMA2_Stream5->CR &= ~(DMA_SxCR_CT);
            
            //enable DMA
            //使锟斤拷DMA
            __HAL_DMA_ENABLE(&hdma_usart1_rx);

            if(this_time_rx_len == NUCINFO_FRAME_LENGTH)
            {   
                //锟斤拷锟斤拷nuc锟斤拷锟斤拷锟斤拷锟斤拷
                sbus_to_nucCtrl(nucinfo_rx_buf[1], &nuc_ctrl);
                if(verifiy_pass())
                {
                    detect_hook(MINI_PC_TOE);
                    gimbal_set_read_mark();
                    shoot_set_read_mark();
                }
            }
        }
    }
}

/**
  * @brief          nuc锟斤拷锟斤拷协锟斤拷锟斤拷锟�
  * @param[in]      sbus_buf: 原锟斤拷锟斤拷锟斤拷指锟斤拷
  * @param[out]     rc_ctrl: nuc锟斤拷锟斤拷指锟斤拷
  * @retval         none
  */

//锟斤拷锟捷斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟皆的达拷锟捷癸拷锟斤拷锟斤拷锟角凤拷为锟斤拷确锟侥ｏ拷锟斤拷锟斤拷锟角凤拷岱达拷锟斤拷锟�??

static void sbus_to_nucCtrl(volatile const uint8_t *sbus_buf, toSTM32_t *nuc_ctrl)
{
    if (sbus_buf == NULL || nuc_ctrl == NULL)
    {
        return;
    }
    (*nuc_ctrl)=(*((toSTM32_t*)sbus_buf));
}

//锟揭碉拷锟剿凤拷锟斤拷1锟斤拷未锟揭碉拷锟津返伙拷0.锟斤拷锟斤拷锟酵碉拷found锟街讹拷为1锟斤拷为锟揭碉拷
int foundArmor(void)
{
    #ifndef TEST_USART
    if(toe_is_error(MINI_PC_TOE))
        return 0;
    if(nuc_ctrl.found_armor == 1)
        return 1;
    else
        return 0;
    #endif
}


/**
  * @brief          send nuc data by usart1
  * @param[in]      data: toNUC data, 32 bytes
  * @retval         none
  */
/**
  * @brief          通锟斤拷usart1锟斤拷锟斤拷sbus锟斤拷锟斤拷,锟斤拷usart3_IRQHandle锟斤拷锟斤拷
  * @param[in]      data: sbus锟斤拷锟斤拷, 32锟街斤拷
  * @retval         none
  */
void send_to_nuc(toNUC_t * data)
{
    static uint8_t usart_tx_buf[sizeof(toNUC_t)];
    memcpy(usart_tx_buf, (uint8_t*)data, sizeof(toNUC_t));
    usart1_tx_dma_enable(usart_tx_buf, sizeof(toNUC_t));
}

toNUC_t toNUCData={0,0,0,0,0,0,0,0,0,0};

void to_nuc_send_task(void const *pvParameters)
{
    osDelay(1000);
    while(1)
    {
        // new
        #ifdef TEST_USART
        if(verifiy_pass()){
            toNUCData=nuc_ctrl;
        }
        #else
        get_toNUCData(&toNUCData);
        #endif
        send_to_nuc(&toNUCData);
        osDelay(100);
    }
}

#ifdef SHOW_UART_TO_NUC
static int calc_sum(void)
{
    int8_t i;
    uint8_t sum = 0;
    uint8_t * data = (uint8_t *) &nuc_ctrl;
    for(i=1;i<sizeof(toSTM32_t)-2;i++)
        sum += data[i];
    return sum;
}


void OLED_USART(void){
    OLED_printf(0,0,"p:%d y:%d x:%d y:%d w:%d shoot:%d check:%d",nuc_ctrl.pitch,nuc_ctrl.yaw,nuc_ctrl.x,nuc_ctrl.y,nuc_ctrl.w,nuc_ctrl.shoot,calc_sum());
                                                                                                                        }
#endif


